package com.paradogs.gs.modules.world;

import com.paradogs.common._cfg.Cfg;
import com.paradogs.common.utils.StreamUtils;
import com.paradogs.common.utils.Wrap;
import com.paradogs.gs.db.WorldNodeDB;
import com.paradogs.gs.misc.BaseService;
import com.paradogs.gs.modules.WorldObject;
import com.paradogs.gs.modules.world.base.unit.WorldMonster;
import com.paradogs.gs.modules.world.base.unit.WorldNPC;
import com.paradogs.gs.modules.world.dao.WorldNodeDBDao;
import com.paradogs.gs.modules.world.entity.BigWorld;
import com.paradogs.gs.modules.world.entity.WorldNode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * @author: yumi
 * @date: 2025/3/31  15:47
 * @Description: 大世界服务
 */
@Slf4j
@Component
public class WorldService extends BaseService {

    @Autowired
    private WorldNodeDBDao worldNodeDao;

    private Map<Integer, BigWorld> worldMap;

    // 单位刷新计数池，每生成一个单位，计数就会 -1，然后等待重置 +1
    private Map<Integer, Integer> unitRTPool = new LinkedHashMap<>();

    @Override
    public void onStart() {
        // 加载大世界
        loadWorlds();
    }

    @Override
    public void onUpdate() {
        // 单位刷新检测
        tryUnitRT();
    }

    private void loadWorlds() {
        // 加载世界
        List<BigWorld> worlds = StreamUtils.map(Cfg.Scene.list(), (cfgScene) -> {
            // 加载节点
            List<WorldNodeDB> nodeDBs = worldNodeDao.list(Wrap.<WorldNodeDB>lbq().eq(WorldNodeDB::getSceneId, cfgScene.id()));
            List<WorldNode> nodes = StreamUtils.map(nodeDBs, WorldNode::new);
            Map<String, WorldNode> cache = StreamUtils.toMap(nodes, WorldNode::key, it -> it);
            // 加载周围节点
            for (WorldNode node : nodes) {
                node.link(cache);
            }
            return new BigWorld(cfgScene.id(), StreamUtils.toMap(nodes, WorldNode::key, node -> node));
        });
        this.worldMap = StreamUtils.toMap(worlds, BigWorld::getId, it -> it);
    }

    public BigWorld getBigWorld(Integer id) {
        return worldMap.get(id);
    }

    private void tryUnitRT() {
        for (Cfg.WorldUnit template : Cfg.WorldUnit.list()) {
            Integer count = unitRTPool.computeIfAbsent(template.id(), (k) -> 1);
            if (count <= 0) {
                continue;
            }
            // 在场景中创建单位
            WorldObject worldObject = null;
            WorldObject.UnitType unitType = WorldObject.UnitType.of(template.unitType());
            if (unitType == WorldObject.UnitType.MONSTER) {
                worldObject = new WorldMonster(template, () -> unitRTPool.computeIfPresent(template.id(), (k, v) -> v + 1));

            } else if (unitType == WorldObject.UnitType.NPC) {
                worldObject = new WorldNPC(template,  () -> unitRTPool.computeIfPresent(template.id(), (k, v) -> v + 1));
            }
            worldObject.born();
            unitRTPool.computeIfPresent(template.id(), (k, v) -> v - 1);
            log.info("[World]Born >>> {}", worldObject);
        }

    }

}
